package com.etone.smartAudit.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.etone.smartAudit.commService.CommPUumUserinfoService;
import com.etone.smartAudit.constant.WorkOrderConstant;
import com.etone.smartAudit.domain.*;
import com.etone.smartAudit.domain.work.*;
import com.etone.smartAudit.dto.wordOrder.ImWorkOrderDTO;
import com.etone.smartAudit.dto.wordOrder.WorkOrderDTO;
import com.etone.smartAudit.enums.WorkRectifyType;
import com.etone.smartAudit.error.CustomParameterizedException;
import com.etone.smartAudit.mapper.*;
import com.etone.smartAudit.onlyoffice.util.WorkOrderListener;
import com.etone.smartAudit.utils.DateUtil;
import com.etone.smartAudit.utils.Excel.ExcelUtil;
import com.etone.smartAudit.vo.PagerVO;
import com.etone.smartAudit.vo.workOrder.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 张任豪
 */
@Service
@Slf4j
public class WorkOrderService extends ServiceImpl<WorkOrderMapper, WorkOrder> {

    @Value("${audit.filePath}")
    private String filePath;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Autowired
    private WorkOrderMapper workOrderMapper;
    @Autowired
    private WorkAuditLogMapper workAuditLogMapper;
    @Autowired
    private WorkOrderRectifyService workOrderRectifyService;
    @Autowired
    private WorkRectifyCheckMapper workRectifyCheckMapper;
    @Autowired
    private WorkRectifyHistoryMapper workRectifyHistoryMapper;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private FileUploadService fileUploadService;
    @Autowired
    private CommPUumUserinfoService pUumUserinfoService;
    @Autowired
    private ItemMapper itemMapper;
    @Autowired
    private ItemTypeMapper itemTypeMapper;


    /**
     * 创建工单
     *
     * @param dto
     * @param admin
     * @param userID
     * @return
     */
    public ResponseVO add(WorkOrderDTO dto, Admin admin, String userID) {
        //生成整改编号
        String code = getRectifyCode();

        WorkOrder workOrder = new WorkOrder();
        BeanUtils.copyProperties(dto, workOrder);
        //计算审计总金额
        Double auditAllAmount = 0.0;
        if (dto.getOutBill() != null) {
            auditAllAmount += dto.getOutBill();
        }
        if (dto.getCoffers() != null) {
            auditAllAmount += dto.getCoffers();
        }
        if (dto.getMishandleAmount() != null) {
            auditAllAmount += dto.getMishandleAmount();
        }
        if (dto.getMayLossAmount() != null) {
            auditAllAmount += dto.getMayLossAmount();
        }
        if (dto.getIrregularAmount() != null) {
            auditAllAmount += dto.getIrregularAmount();
        }
        if (dto.getLossAmount() != null) {
            auditAllAmount += dto.getLossAmount();
        }
        workOrder.setAuditRiskAmount(auditAllAmount);
        workOrder.setRectifyCode(code);
        //设置工单责任人部门
        PUumUserinfo pUumUserinfo = pUumUserinfoService.getOne(new QueryWrapper<PUumUserinfo>().eq("userID", dto.getWordOrderAccount()));
        if (pUumUserinfo != null) {
            workOrder.setWorkOrderDeptID(pUumUserinfo.getDepartmentID());
        } else {
            throw new CustomParameterizedException("当前登录用户不在port组织机构中");
        }
        //设置工单责任人
        Admin account = adminMapper.findByAccount(dto.getWordOrderAccount());
        if (account != null) {
            workOrder.setWordOrderName(account.getNickName());
            workOrder.setWordOrderId(account.getId());
        } else {
            throw new CustomParameterizedException("该工单接收人未在审计平台注册账号");
        }
        //更改工单状态,审核人信息
        if (!StringUtils.isEmpty(userID)) {
            Admin auditMan = adminMapper.findByAccount(userID);
            if (auditMan != null) {
                workOrder.setAuditManId(auditMan.getId());
                workOrder.setStatus(WorkOrderConstant.WORK_STATUS_AUDIT);
                workOrder.setStepStatus(!"R_OFFICE".equals(admin.getRole().getCode())
                        ? WorkOrderConstant.WORK_STATE_MANAGER_AUDIT : WorkOrderConstant.WORK_STATE_GROUP_AUDIT);
                //获取审核人信息
                workOrder.setAuditMan(auditMan.getNickName());
            } else {
                throw new CustomParameterizedException("审核人未在审计平台注册账号,事务所角色不能直接提交审核人");
            }
        }
        workOrder.setAuditStage(WorkOrderConstant.WORK_SUBMIT_STAGE);
        //设置创建用户和时间
        workOrder.setCreateAdmin(admin.getId());
        workOrder.setCreateDate(new Date());
        workOrderMapper.insert(workOrder);
        addWorkAuditLog(workOrder.getIntId(),admin.getId(),"创建工单","审核",null);
        return ResponseVO.success("保存成功");
    }

    /**
     * 更新工单信息
     *
     * @param dto
     * @param admin
     * @param id
     * @param userID
     * @return
     */
    public Object update(WorkOrderDTO dto, Admin admin, Integer id, String userID) {
        WorkOrder workOrder = workOrderMapper.selectById(id);
        workOrder.setUpdateAdmin(admin.getId());
        workOrder.setUpdateDate(new Date());
        //计算审计总金额
        Double auditAllAmount = 0.0;
        if (dto.getOutBill() != null) {
            auditAllAmount += dto.getOutBill();
        }
        if (dto.getCoffers() != null) {
            auditAllAmount += dto.getCoffers();
        }
        if (dto.getMishandleAmount() != null) {
            auditAllAmount += dto.getMishandleAmount();
        }
        if (dto.getMayLossAmount() != null) {
            auditAllAmount += dto.getMayLossAmount();
        }
        if (dto.getIrregularAmount() != null) {
            auditAllAmount += dto.getIrregularAmount();
        }
        if (dto.getLossAmount() != null) {
            auditAllAmount += dto.getLossAmount();
        }
        workOrder.setAuditRiskAmount(auditAllAmount);
        //设置工单责任人
        Admin account = adminMapper.findByAccount(dto.getWordOrderAccount());
        if (account != null) {
            workOrder.setWordOrderName(account.getNickName());
            workOrder.setWordOrderId(account.getId());
        } else {
            throw new CustomParameterizedException("该工单接收人未在审计平台注册账号");
        }
        //设置派发审核人
        if (userID != null) {
            Admin auditMan = adminMapper.findByAccount(userID);
            if (auditMan != null) {
                workOrder.setAuditManId(auditMan.getId());
                workOrder.setAuditMan(auditMan.getNickName());
                workOrder.setStatus(WorkOrderConstant.WORK_STATUS_AUDIT);
                workOrder.setStepStatus(!"R_OFFICE".equals(admin.getRole().getCode())
                        ? WorkOrderConstant.WORK_STATE_MANAGER_AUDIT : WorkOrderConstant.WORK_STATE_GROUP_AUDIT);
            } else {
                throw new CustomParameterizedException("该审核人未在审计平台注册账号");
            }
        }


        //判断是否已经上传文件
        if (workOrder.getAuditFileUrl() != null && dto.getAuditFileUrl() != null) {
            fileUploadService.deleteFileByURL(Arrays.asList(workOrder.getAuditFileUrl()), true, true);
        }
        BeanUtils.copyProperties(dto, workOrder);
        //处理文件
        return workOrderMapper.updateById(workOrder);
    }

    /**
     * 工单详情
     *
     * @param id
     * @return
     */
    public WorkOrderDetailVO detail(Integer id) {
        WorkOrder workOrder = workOrderMapper.selectById(id);
        Admin admin = adminMapper.selectById(workOrder.getWordOrderId());
        //返回工单接收人信息
        workOrder.setWordOrderAccount(admin.getAccount());
        workOrder.setWordOrderTel(admin.getTel());
        Admin auditGroup = adminMapper.findByAccount(workOrder.getAuditGroupAccount());
        workOrder.setAuditGroupTel(auditGroup.getTel());

        //反馈责任人电话，相关责任人电话
        WorkRectify rectify = workOrderRectifyService.getByWorkId(id);
        String chargeManTel = "";
        String chargeRelateManTel = "";
        if (rectify != null) {
            chargeManTel = adminMapper.selectById(rectify.getChargeManId()).getTel();
            String chargeRelateManAccount = rectify.getChargeRelateManAccount();
            if (!StringUtils.isEmpty(chargeRelateManAccount)) {
                String[] split = chargeRelateManAccount.split(",");
                for (String account : split) {
                    Admin account1 = adminMapper.findByAccount(account);
                    chargeRelateManTel += account1.getTel() + ",";
                }
            }
        }

        //验收信息
        WorkRectifyCheck rectifyCheck = workRectifyCheckMapper.getByWork(id);
        if (rectifyCheck != null) {
            Admin chargeMan = adminMapper.selectById(rectifyCheck.getChargeId());
            rectifyCheck.setChargeManTel(chargeMan.getTel());
        }

        //审核流程
        List<WorkOrderDetailVO.LogVO> logVO = getLogVO(id);

        return WorkOrderDetailVO.builder()
                .workOrder(workOrder)
                .workRectifies(workOrderRectifyService.list(id))
                .rectifyCheck(rectifyCheck)
                .logVOS(logVO)
                .chargeManTel(chargeManTel)
                .chargeRelateManTel(chargeRelateManTel)
                .build();
    }

    /**
     * 工单列表
     *
     * @param page
     * @param pageSize
     * @param name
     * @param rectifyCode
     * @param startDate
     * @param endDate
     * @param status
     * @param isOverdue
     * @param wordOrderName
     * @param keyword
     * @param admin
     * @return
     */
    public PagerVO<WorkOrderVO> listWorkOrder(int page, int pageSize, String name, String rectifyCode, Date startDate, Date endDate, Integer status, Integer isOverdue, String wordOrderName, String keyword, Admin admin) {
        if ("R_SUBMIT".equals(admin.getRole().getCode())) {
            admin.setRoleId(1);
        }
        PUumUserinfo uumUserinfo = pUumUserinfoService.getOne(new QueryWrapper<PUumUserinfo>().eq("userID", admin.getAccount()));
        if (uumUserinfo == null && !admin.isAdmin()) {
            throw new CustomParameterizedException("你未在port组织结构中,也不是管理员，所有无权访问");
        }
        Page<WorkOrderVO> doSelectPage = PageHelper.startPage(page, pageSize).doSelectPage(() -> {
            workOrderMapper.listWorkOrder(name, rectifyCode, startDate, endDate, status, isOverdue, wordOrderName, keyword, admin.getRoleId(), null, uumUserinfo.getCompany());
        });
        return PagerVO.of(doSelectPage);
    }

    /**
     * 我的工单列表
     *
     * @param page
     * @param pageSize
     * @param name
     * @param rectifyCode
     * @param startDate
     * @param endDate
     * @param status
     * @param isOverdue
     * @param wordOrderName
     * @param keyword
     * @param admin
     * @return
     */
    public PagerVO<WorkOrderVO> listMyWorkOrder(int page, int pageSize, String name, String rectifyCode, Date startDate, Date endDate, Integer status, Integer isOverdue, String wordOrderName, String keyword, Admin admin) {
        Page<WorkOrderVO> doSelectPage = PageHelper.startPage(page, pageSize).doSelectPage(() -> {
            workOrderMapper.listWorkOrder(name, rectifyCode, startDate, endDate, status, isOverdue, wordOrderName, keyword, admin.getRoleId(), admin.getId(), null);
        });
        return PagerVO.of(doSelectPage);
    }

    public Integer deleteAll(List<Integer> ids, String msg) {
        int count = workOrderMapper.deleteBatchIds(ids);
        for (Integer id : ids) {
            //删除日志信息
            workAuditLogMapper.delete(new QueryWrapper<WorkAuditLog>().eq("intWorkId",id));
            //删除反馈信息
            workOrderRectifyService.delete(id);
            //删除整改信息
            workRectifyCheckMapper.delete(new QueryWrapper<WorkRectifyCheck>().eq("intWorkId",id));
            //删除反馈历史
            workRectifyHistoryMapper.delete(new QueryWrapper<WorkRectifyHistory>().eq("intWorkId",id));
        }
        return count;
    }

    /**
     * 批量工单导入
     *
     * @param file
     * @return
     */
    public ImportWorkVO importWork(MultipartFile file) {
        ImportWorkVO importWorkVO = new ImportWorkVO();
        try {
            List<ImWorkOrderDTO> list = EasyExcel.read(file.getInputStream(), ImWorkOrderDTO.class, new WorkOrderListener(pUumUserinfoService, adminMapper, itemMapper, itemTypeMapper)).headRowNumber(3).sheet().doReadSync();
            int fail = (int) list.stream().filter(ImWorkOrderDTO::getIsError).count();
            Integer success = list.size() - fail;
            importWorkVO.setData(list);
            importWorkVO.setFail(fail);
            importWorkVO.setSuccess(success);
            importWorkVO.setFileName(file.getOriginalFilename());
            importWorkVO.setFileSize(file.getSize());
        } catch (IOException e) {
            log.info("导入异常:{}", e.getMessage());
            throw new CustomParameterizedException("导入异常");
        }
        return importWorkVO;
    }

    /**
     * 批量派发
     */
    public ResponseVO batchSend(String auditAccount, List<Integer> workIds, Admin admin) {
        try {
            Admin audit = adminMapper.findByAccount(auditAccount);
            int success = 0;
            int fail = 0;
            //跟新工单审核流程
            for (Integer workId : workIds) {
                WorkOrder workOrder = workOrderMapper.selectById(workId);
                if (workOrder.getCreateAdmin().equals(admin.getId()) || admin.isAdmin()) {
                    Admin create = adminMapper.findByAccount(adminMapper.selectById(workOrder.getCreateAdmin()).getAccount());
                    //更新所有的工单状态
                    if ("R_OFFICE".equals(create.getRole().getCode())) {
                        if (workOrder.getStepStatus().equals(WorkOrderConstant.WORK_STATE_CREATE)) {
                            workOrderMapper.updateState(audit.getId(), audit.getNickName(), workId, WorkOrderConstant.WORK_STATE_GROUP_AUDIT);
                        }else {
                            workOrderMapper.updateState(audit.getId(), audit.getNickName(), workId, WorkOrderConstant.WORK_STATE_MANAGER_AUDIT);
                        }
                    }else {
                        workOrderMapper.updateState(audit.getId(), audit.getNickName(), workId, WorkOrderConstant.WORK_STATE_MANAGER_AUDIT);
                    }
                    success += 1;
                } else {
                    fail += 1;
                }
            }

            return ResponseVO.success("成功派发:" + success + "条,失败" + fail + "条");
        } catch (Exception e) {
            throw new CustomParameterizedException("派发异常:" + e.getMessage());
        }
    }


    public OrderFileVO fileUpload(MultipartFile file) {
        if (file == null) {
            throw new CustomParameterizedException("上传附件不能为空");
        }
        String type = "workOrder";
        File curPath = new File(filePath + "/" + type);
        if (!curPath.exists()) {
            curPath.mkdirs();
        }
        Random random = new Random();
        //原文件名
        String originalFilename = file.getOriginalFilename();
        //扩展名
        String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        //文件名
        String uploadName = System.currentTimeMillis() + "_" + String.format("%05d", random.nextInt(100000)) + "." + extension;
        String relativePath = type + "/" + uploadName;
        String url = contextPath + "/upload/files/" + relativePath;
        File curFile = new File(filePath + "/" + relativePath);
        OrderFileVO orderFileVO = null;
        try {
            orderFileVO = OrderFileVO.builder()
                    .auditFileName(uploadName)
                    .auditFileOriginName(file.getOriginalFilename())
                    .auditFileType(type)
                    .auditFileUrl(url)
                    .build();
            file.transferTo(curFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return orderFileVO;
    }

    public ResponseVO<Integer> batchAddOrder(List<ImWorkOrderDTO> imWorkOrderDTOS, Admin admin) {
        int count = 0;
        if (!imWorkOrderDTOS.isEmpty()) {

            List<WorkOrder> workOrderList = new ArrayList<>();
            for (ImWorkOrderDTO workOrderDTO : imWorkOrderDTOS) {
                WorkOrder workOrder = new WorkOrder();
                BeanUtils.copyProperties(workOrderDTO, workOrder);
                //设置工单初始状态
                workOrder.setRectifyCode(getRectifyCode());
                workOrder.setCreateAdmin(admin.getId());
                workOrder.setCreateDate(new Date());
                //计算审计总金额
                Double auditAllAmount = 0.0;
                if (workOrderDTO.getOutBill() != null) {
                    auditAllAmount += workOrderDTO.getOutBill();
                }
                if (workOrderDTO.getCoffers() != null) {
                    auditAllAmount += workOrderDTO.getCoffers();
                }
                if (workOrderDTO.getMishandleAmount() != null) {
                    auditAllAmount += workOrderDTO.getMishandleAmount();
                }
                if (workOrderDTO.getMayLossAmount() != null) {
                    auditAllAmount += workOrderDTO.getMayLossAmount();
                }
                if (workOrderDTO.getIrregularAmount() != null) {
                    auditAllAmount += workOrderDTO.getIrregularAmount();
                }
                if (workOrderDTO.getLossAmount() != null) {
                    auditAllAmount += workOrderDTO.getLossAmount();
                }
                workOrder.setAuditRiskAmount(auditAllAmount);
                workOrder.setRectifyStartDate(new Date());
                //添加部门ID
                Admin wordOrder = adminMapper.selectById(workOrderDTO.getWordOrderId());
                PUumUserinfo userinfo = pUumUserinfoService.getOne(new QueryWrapper<PUumUserinfo>().eq("userID", wordOrder.getAccount()));
                workOrder.setWorkOrderDeptID(userinfo.getDepartmentID());
                if (!workOrderDTO.getIsError()) {
                    workOrderList.add(workOrder);
                }
            }
            //保存工单
            if (workOrderList.size() > 0) {
                count = workOrderMapper.saveAll(workOrderList);
            }
        }
        return ResponseVO.success("成功导入" + count + "条数据");
    }

    /**
     * 工单导出
     *
     * @param list
     * @param response
     */
    public void exportOrder(List<WorkOrderVO> list, HttpServletResponse response) {
        //头文件
        List<String> header = Arrays.asList("整改事项编号", "年份", "项目类型", "项目名称", "被审计单位", "反馈时间", "整改时限", "审计组联系人", "整改结果确定", "工单状态");

        //导出数据
        List<List<String>> contents = list.stream().map(vo ->
                Arrays.asList(vo.getRectifyCode(), vo.getYear(), vo.getItemTypeName(), vo.getItemName(), vo.getAuditUnit(), parseDate(vo.getFeedBack()),
                        parseDate(vo.getRectifyEndDate()), vo.getAuditGroup(), vo.getRectifyResult(), vo.getOrderState())
        ).collect(Collectors.toList());
        ExcelUtil.export("工单列表", header, contents, response);
    }


    public String parseDate(Date time) {
        if (time == null) {
            return null;
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(time);
    }


    /**
     * 工单导入模板
     *
     * @param response
     */
    public void orderTemplate(HttpServletResponse response) {
        String path = "tfs/workOrder_template.xlsx";
        InputStream inputStream = ResourceUtil.getStream(path);
        fileUploadService.getFile(inputStream, response, "工单导入模板.xlsx");
    }


    /**
     * 推送代办信息productMaps
     */
    public void pushTodoTask() {


    }

    /**
     * 判断是否有权限修改工单
     *
     * @param id    工单id
     * @param admin 当前登录用户
     */
    public ResponseVO isPermissionUpdate(Integer id, Admin admin) {
        WorkOrder workOrder = workOrderMapper.selectById(id);
        WorkRectify rectify = workOrderRectifyService.getByWorkId(id);
        WorkRectifyCheck rectifyCheck = workRectifyCheckMapper.getByWork(id);
        if (admin.getIsSuper()) {
            return ResponseVO.success();
        }
        switch (workOrder.getStatus()) {
            //待派发
            case 0:
                if (!(workOrder.getCreateAdmin().equals(admin.getId())
                        || workOrder.getAuditGroupAccount().equals(admin.getAccount())
                        || admin.isAdmin())) {
                    return ResponseVO.fail("你没有权限修改");
                } else {
                    return ResponseVO.success();
                }
            //待审核
            case 1:
                if (!(workOrder.getAuditManId().equals(admin.getId()) || admin.isAdmin())) {
                    return ResponseVO.fail("工单处于审核状态，不能随意编辑");
                } else {
                    return ResponseVO.success();
                }
            //待反馈
            case 2:
                if ((rectify.getChargeManId().equals(admin.getId())
                        || rectify.getChargeRelateManAccount().contains(admin.getAccount()) || admin.isAdmin())) {
                    return ResponseVO.success();
                }
            //待验收
            case 3:
                if (((rectifyCheck.getCheckStep().equals(WorkOrderConstant.WORK_CHECK_PASS)) && workOrder.getAuditGroupAccount().equals(admin.getAccount())) || admin.isAdmin()) {
                    return ResponseVO.success();
                } else if ((rectifyCheck.getCheckStep().equals(WorkOrderConstant.WORK_CHECK_AUDIT) && rectifyCheck.getChargeId().equals(admin.getId())) || admin.isAdmin()) {
                    return ResponseVO.success();
                }
            default:
                return ResponseVO.fail("该用户没有编辑修改该工单的权限");
        }
    }


    //审核流程
    public List<WorkOrderDetailVO.LogVO> getLogVO(Integer workId) {

        List<WorkOrderDetailVO.LogVO> logVOS = new ArrayList<>();
        List<WorkAuditLog> auditLogs = workAuditLogMapper.selectList(new QueryWrapper<WorkAuditLog>().eq("intWorkId",workId).orderByAsc("dtExecuteTime"));
        if (CollectionUtil.isNotEmpty(auditLogs)){
            for (WorkAuditLog auditLog : auditLogs) {
                WorkOrderDetailVO.LogVO logVO = WorkOrderDetailVO.LogVO.builder()
                        .auditMan(auditLog.getExecute())
                        .auditTime(auditLog.getExecuteTime())
                        .flowStep(auditLog.getFlowStep())
                        .nextFlow(auditLog.getNextFlow())
                        .remark(auditLog.getRemark()).build();
                logVOS.add(logVO);
            }
        }
        return logVOS;
    }

    /**
     * 获取整改编码
     */
    public String getRectifyCode() {
        String dateStr = DateUtil.parseDate2String(new Date(), "yyyy");
        return dateStr + RandomUtil.randomString(10);
    }

    /**
     * 添加审核流程
     */
    public void addWorkAuditLog(Integer workId,Integer executeId,String flowStep,String nextFlow,String remark){
        Admin execute = adminMapper.selectById(executeId);
        WorkAuditLog auditLog = WorkAuditLog.builder()
                .executeId(executeId)
                .execute(execute.getNickName())
                .executeTime(new Date())
                .flowStep(flowStep)
                .nextFlow(nextFlow)
                .remark(remark)
                .workId(workId).build();
        workAuditLogMapper.insert(auditLog);
    }
}
